home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src / vbxform.c < prev    next >
C/C++ Source or Header  |  1999-02-04  |  46KB  |  1,557 lines

  1. /* $Id: vbxform.c,v 3.10 1998/08/23 22:19:30 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: vbxform.c,v $
  26.  * Revision 3.10  1998/08/23 22:19:30  brianp
  27.  * added DoViewportMapping to context struct
  28.  *
  29.  * Revision 3.9  1998/07/09 03:15:41  brianp
  30.  * include asm_386.h instead of asm-386.h
  31.  *
  32.  * Revision 3.8  1998/06/22 03:16:28  brianp
  33.  * added MITS code
  34.  *
  35.  * Revision 3.7  1998/06/07 22:18:52  brianp
  36.  * implemented GL_EXT_multitexture extension
  37.  *
  38.  * Revision 3.6  1998/04/18 05:01:18  brianp
  39.  * renamed USE_ASM to USE_X86_ASM
  40.  *
  41.  * Revision 3.5  1998/03/28 04:01:53  brianp
  42.  * added CONST macro to fix IRIX compilation problems
  43.  *
  44.  * Revision 3.4  1998/03/27 04:26:44  brianp
  45.  * fixed G++ warnings
  46.  *
  47.  * Revision 3.3  1998/02/20 04:53:07  brianp
  48.  * implemented GL_SGIS_multitexture
  49.  *
  50.  * Revision 3.2  1998/02/02 03:09:34  brianp
  51.  * added GL_LIGHT_MODEL_COLOR_CONTROL (separate specular color interpolation)
  52.  *
  53.  * Revision 3.1  1998/02/01 16:37:19  brianp
  54.  * added GL_EXT_rescale_normal extension
  55.  *
  56.  * Revision 3.0  1998/01/31 21:06:45  brianp
  57.  * initial rev
  58.  *
  59.  */
  60.  
  61.  
  62. /*
  63.  * This file implements transformation, clip testing and projection of
  64.  * vertices in the vertex buffer.
  65.  *
  66.  * The entry points to this file are the functions:
  67.  *    gl_transform_vb_part1() - first stage of vertex transformation
  68.  *    gl_transform_vb_part2() - second stage of vertex transformation
  69.  */
  70.  
  71.  
  72. #ifdef PC_HEADER
  73. #include "all.h"
  74. #else
  75. #include <stdlib.h>
  76. #include "asm_386.h"
  77. #include "context.h"
  78. #include "fog.h"
  79. #include "light.h"
  80. #include "macros.h"
  81. #include "matrix.h"
  82. #include "mmath.h"
  83. #include "shade.h"
  84. #include "texture.h"
  85. #include "types.h"
  86. #include "vb.h"
  87. #include "vbrender.h"
  88. #include "vbxform.h"
  89. #include "xform.h"
  90. #endif
  91.  
  92. #if defined(AMIGA) && defined(__PPC__)
  93. void asm_vp_map_vertices_now(const GLubyte clipMask[],int n,GLfloat vWin[][3],const GLfloat vClip[][4],
  94.                  GLfloat sx, GLfloat sy, GLfloat sz,
  95.                  GLfloat tx, GLfloat ty, GLfloat tz);
  96. void asm_vp_map_vertices(const GLubyte clipMask[],int n,GLfloat vWin[][3],const GLfloat vClip[][4],
  97.              GLfloat sx, GLfloat sy, GLfloat sz,
  98.              GLfloat tx, GLfloat ty, GLfloat tz);
  99. #endif
  100.  
  101. #ifdef PROFILE
  102. #define START_PROFILE t0 = gl_time();
  103. #define END_PROFILE( TIMER) TIMER += (gl_time() - t0);
  104.  
  105.   GLdouble t0,t1;
  106.   GLdouble prof1_time,prof2_time,prof3_time,prof4_time,prof5_time,prof6_time,prof7_time,prof8_time,profrender_time;
  107. #else
  108. #define START_PROFILE
  109. #define END_PROFILE( TIMER)
  110. #endif
  111.  
  112. #ifdef AMIGA
  113. #define START_PROFILE3
  114. #define END_PROFILE3( TIMER)
  115. #endif
  116.  
  117. #if !defined(NOASM_68K) && !defined(NOASM_PPC)
  118. #define USE_X86_ASM
  119. #endif
  120.  
  121. #if 0  /* NOT USED AT THIS TIME */
  122. /*
  123.  * Use the current modelview matrix to transform XY vertices from object
  124.  * to eye coordinates.
  125.  * Input:  ctx - the context
  126.  *         n - number of vertices to transform
  127.  *         vObj - array [n][4] of object coordinates
  128.  * In/Out;  vEye - array [n][4] of eye coordinates
  129.  */
  130. static void transform_points2( GLcontext *ctx, GLuint n,
  131.                    const GLfloat vObj[][4], GLfloat vEye[][4] )
  132. {
  133.    switch (ctx->ModelViewMatrixType) {
  134.       case MATRIX_GENERAL:
  135.      {
  136.         const GLfloat *m = ctx->ModelViewMatrix;
  137.         GLfloat m0 = m[0],  m4 = m[4],  m12 = m[12];
  138.         GLfloat m1 = m[1],  m5 = m[5],  m13 = m[13];
  139.         GLfloat m2 = m[2],  m6 = m[6],  m14 = m[14];
  140.         GLfloat m3 = m[3],  m7 = m[7],  m15 = m[15];
  141.         GLuint i;
  142.         for (i=0;i<n;i++) {
  143.            GLfloat ox = vObj[i][0], oy = vObj[i][1];
  144.            vEye[i][0] = m0 * ox + m4 * oy + m12;
  145.            vEye[i][1] = m1 * ox + m5 * oy + m13;
  146.            vEye[i][2] = m2 * ox + m6 * oy + m14;
  147.            vEye[i][3] = m3 * ox + m7 * oy + m15;
  148.         }
  149.      }
  150.      break;
  151.       case MATRIX_IDENTITY:
  152.      {
  153.         GLuint i;
  154.         for (i=0;i<n;i++) {
  155.            vEye[i][0] = vObj[i][0];
  156.            vEye[i][1] = vObj[i][1];
  157.            vEye[i][2] = 0.0F;
  158.            vEye[i][3] = 1.0F;
  159.         }
  160.      }
  161.      break;
  162.       case MATRIX_2D:
  163.      {
  164.         const GLfloat *m = ctx->ModelViewMatrix;
  165.         GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  166.         GLfloat m12 = m[12], m13 = m[13];
  167.         GLuint i;
  168.         for (i=0;i<n;i++) {
  169.            GLfloat ox = vObj[i][0], oy = vObj[i][1];
  170.            vEye[i][0] = m0 * ox + m4 * oy + m12;
  171.            vEye[i][1] = m1 * ox + m5 * oy + m13;
  172.            vEye[i][2] = 0.0F;
  173.            vEye[i][3] = 1.0F;
  174.         }
  175.      }
  176.      break;
  177.       case MATRIX_2D_NO_ROT:
  178.      {
  179.         const GLfloat *m = ctx->ModelViewMatrix;
  180.         GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
  181.         GLuint i;
  182.         for (i=0;i<n;i++) {
  183.            GLfloat ox = vObj[i][0], oy = vObj[i][1];
  184.            vEye[i][0] = m0 * ox           + m12;
  185.            vEye[i][1] =           m5 * oy + m13;
  186.            vEye[i][2] = 0.0F;
  187.            vEye[i][3] = 1.0F;
  188.         }
  189.      }
  190.      break;
  191.       case MATRIX_3D:
  192.      {
  193.         const GLfloat *m = ctx->ModelViewMatrix;
  194.         GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
  195.         GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14];
  196.         GLuint i;
  197.         for (i=0;i<n;i++) {
  198.            GLfloat ox = vObj[i][0], oy = vObj[i][1];
  199.            vEye[i][0] = m0 * ox + m4 * oy + m12;
  200.            vEye[i][1] = m1 * ox + m5 * oy + m13;
  201.            vEye[i][2] = m2 * ox + m6 * oy + m14;
  202.            vEye[i][3] = 1.0F;
  203.         }
  204.      }
  205.      break;
  206.       default:
  207.      /* should never get here */
  208.      gl_problem( NULL, "invalid matrix type in transform_points3()" );
  209.      return;
  210.    }
  211. }
  212. #endif
  213.  
  214.  
  215. /*
  216.  * Use the current modelview matrix to transform XYZ vertices from object
  217.  * to eye coordinates.
  218.  * Input:  ctx - the context
  219.  *         n - number of vertices to transform
  220.  *         vObj - array [n][4] of object coordinates
  221.  * In/Out;  vEye - array [n][4] of eye coordinates
  222.  */
  223. static void transform_points3( GLcontext *ctx, GLuint n,
  224.                    CONST GLfloat vObj[][4], GLfloat vEye[][4] )
  225. {
  226. #ifndef USE_X86_ASM
  227.    START_FAST_MATH;
  228.    switch (ctx->ModelViewMatrixType) {
  229.       case MATRIX_GENERAL:
  230.      {
  231.         const GLfloat *m = ctx->ModelViewMatrix;
  232.         GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  233.         GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  234.         GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  235.         GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  236.         GLuint i;
  237.         for (i=0;i<n;i++) {
  238.            GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
  239.            vEye[i][0] = m0 * ox + m4 * oy + m8  * oz + m12;
  240.            vEye[i][1] = m1 * ox + m5 * oy + m9  * oz + m13;
  241.            vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14;
  242.            vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15;
  243.         }
  244.      }
  245.      break;
  246.       case MATRIX_IDENTITY:
  247.      {
  248.         GLuint i;
  249.         for (i=0;i<n;i++) {
  250.            vEye[i][0] = vObj[i][0];
  251.            vEye[i][1] = vObj[i][1];
  252.            vEye[i][2] = vObj[i][2];
  253.            vEye[i][3] = 1.0F;
  254.         }
  255.      }
  256.      break;
  257.       case MATRIX_2D:
  258.      {
  259.         const GLfloat *m = ctx->ModelViewMatrix;
  260.         GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  261.         GLfloat m12 = m[12], m13 = m[13];
  262.         GLuint i;
  263.         for (i=0;i<n;i++) {
  264.            GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
  265.            vEye[i][0] = m0 * ox + m4 * oy            + m12       ;
  266.            vEye[i][1] = m1 * ox + m5 * oy            + m13       ;
  267.            vEye[i][2] =                   +       oz             ;
  268.            vEye[i][3] =                                      1.0F;
  269.         }
  270.      }
  271.      break;
  272.       case MATRIX_2D_NO_ROT:
  273.      {
  274.         const GLfloat *m = ctx->ModelViewMatrix;
  275.         GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
  276.         GLuint i;
  277.         for (i=0;i<n;i++) {
  278.            GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
  279.            vEye[i][0] = m0 * ox                      + m12       ;
  280.            vEye[i][1] =           m5 * oy            + m13       ;
  281.            vEye[i][2] =                   +       oz             ;
  282.            vEye[i][3] =                                      1.0F;
  283.         }
  284.      }
  285.      break;
  286.       case MATRIX_3D:
  287.      {
  288.         const GLfloat *m = ctx->ModelViewMatrix;
  289.         GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
  290.         GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
  291.         GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
  292.         GLuint i;
  293.         for (i=0;i<n;i++) {
  294.            GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2];
  295.            vEye[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12       ;
  296.            vEye[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13       ;
  297.            vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14       ;
  298.            vEye[i][3] =                                      1.0F;
  299.         }
  300.      }
  301.      break;
  302.       default:
  303.      /* should never get here */
  304.      gl_problem( NULL, "invalid matrix type in transform_points3()" );
  305.    }
  306.    END_FAST_MATH;
  307. #else
  308.    switch (ctx->ModelViewMatrixType) {
  309.       case MATRIX_GENERAL:
  310.      asm_transform_points3_general( n, vEye, ctx->ModelViewMatrix, vObj );
  311.      break;
  312.       case MATRIX_IDENTITY:
  313.      asm_transform_points3_identity( n, vEye, vObj );
  314.      break;
  315.       case MATRIX_2D:
  316.      asm_transform_points3_2d( n, vEye, ctx->ModelViewMatrix, vObj );
  317.      break;
  318.       case MATRIX_2D_NO_ROT:
  319.      asm_transform_points3_2d_no_rot( n, vEye, ctx->ModelViewMatrix,
  320.                       vObj );
  321.      break;
  322.       case MATRIX_3D:
  323.      asm_transform_points3_3d( n, vEye, ctx->ModelViewMatrix, vObj );
  324.      break;
  325.       default:
  326.      /* should never get here */
  327.      gl_problem( NULL, "invalid matrix type in transform_points3()" );
  328.      return;
  329.    }
  330. #endif
  331. }
  332.  
  333.  
  334.  
  335. /*
  336.  * Use the current modelview matrix to transform XYZW vertices from object
  337.  * to eye coordinates.
  338.  * Input:  ctx - the context
  339.  *         n - number of vertices to transform
  340.  *         vObj - array [n][4] of object coordinates
  341.  * In/Out;  vEye - array [n][4] of eye coordinates
  342.  */
  343. static void transform_points4( GLcontext *ctx, GLuint n,
  344.                    CONST GLfloat vObj[][4], GLfloat vEye[][4] )
  345. {
  346. #ifndef USE_X86_ASM
  347.    START_FAST_MATH;
  348.    switch (ctx->ModelViewMatrixType) {
  349.       case MATRIX_GENERAL:
  350.      {
  351.         const GLfloat *m = ctx->ModelViewMatrix;
  352.         GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  353.         GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  354.         GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  355.         GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  356.         GLuint i;
  357.         for (i=0;i<n;i++) {
  358.            GLfloat ox = vObj[i][0], oy = vObj[i][1];
  359.            GLfloat oz = vObj[i][2], ow = vObj[i][3];
  360.            vEye[i][0] = m0 * ox + m4 * oy + m8  * oz + m12 * ow;
  361.            vEye[i][1] = m1 * ox + m5 * oy + m9  * oz + m13 * ow;
  362.            vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
  363.            vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow;
  364.         }
  365.      }
  366.      break;
  367.       case MATRIX_IDENTITY:
  368.      {
  369.         GLuint i;
  370.         for (i=0;i<n;i++) {
  371.            vEye[i][0] = vObj[i][0];
  372.            vEye[i][1] = vObj[i][1];
  373.            vEye[i][2] = vObj[i][2];
  374.            vEye[i][3] = vObj[i][3];
  375.         }
  376.      }
  377.      break;
  378.       case MATRIX_2D:
  379.      {
  380.         const GLfloat *m = ctx->ModelViewMatrix;
  381.         GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  382.         GLfloat m12 = m[12], m13 = m[13];
  383.         GLuint i;
  384.         for (i=0;i<n;i++) {
  385.            GLfloat ox = vObj[i][0], oy = vObj[i][1];
  386.            GLfloat oz = vObj[i][2], ow = vObj[i][3];
  387.            vEye[i][0] = m0 * ox + m4 * oy            + m12 * ow;
  388.            vEye[i][1] = m1 * ox + m5 * oy            + m13 * ow;
  389.            vEye[i][2] =                   +       oz           ;
  390.            vEye[i][3] =                                      ow;
  391.         }
  392.      }
  393.      break;
  394.       case MATRIX_2D_NO_ROT:
  395.      {
  396.         const GLfloat *m = ctx->ModelViewMatrix;
  397.         GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
  398.         GLuint i;
  399.         for (i=0;i<n;i++) {
  400.            GLfloat ox = vObj[i][0], oy = vObj[i][1];
  401.            GLfloat oz = vObj[i][2], ow = vObj[i][3];
  402.            vEye[i][0] = m0 * ox                      + m12 * ow;
  403.            vEye[i][1] =           m5 * oy            + m13 * ow;
  404.            vEye[i][2] =                   +       oz           ;
  405.            vEye[i][3] =                                      ow;
  406.         }
  407.      }
  408.      break;
  409.       case MATRIX_3D:
  410.      {
  411.         const GLfloat *m = ctx->ModelViewMatrix;
  412.         GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
  413.         GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
  414.         GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
  415.         GLuint i;
  416.         for (i=0;i<n;i++) {
  417.            GLfloat ox = vObj[i][0], oy = vObj[i][1];
  418.            GLfloat oz = vObj[i][2], ow = vObj[i][3];
  419.            vEye[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12 * ow;
  420.            vEye[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13 * ow;
  421.            vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
  422.            vEye[i][3] =                                      ow;
  423.         }
  424.      }
  425.      break;
  426.       default:
  427.      /* should never get here */
  428.      gl_problem( NULL, "invalid matrix type in transform_points4()" );
  429.    }
  430.    END_FAST_MATH;
  431. #else
  432.    switch (ctx->ModelViewMatrixType) {
  433.       case MATRIX_GENERAL:
  434.      asm_transform_points4_general( n, vEye, ctx->ModelViewMatrix, vObj );
  435.      break;
  436.       case MATRIX_IDENTITY:
  437.      asm_transform_points4_identity( n, vEye, vObj );
  438.      break;
  439.       case MATRIX_2D:
  440.      asm_transform_points4_2d( n, vEye, ctx->ModelViewMatrix, vObj );
  441.      break;
  442.       case MATRIX_2D_NO_ROT:
  443.      asm_transform_points4_2d_no_rot( n, vEye, ctx->ModelViewMatrix,
  444.                       vObj );
  445.      break;
  446.       case MATRIX_3D:
  447.      asm_transform_points4_3d( n, vEye, ctx->ModelViewMatrix, vObj );
  448.      break;
  449.       default:
  450.      /* should never get here */
  451.      gl_problem( NULL, "invalid matrix type in transform_points4()" );
  452.      return;
  453.    }
  454. #endif
  455. }
  456.  
  457.  
  458.  
  459. /*
  460.  * Transform an array of texture coordinates by the current texture matrix.
  461.  * Input:  ctx - the context
  462.  *         n - number of texture coordinates in array
  463.  *         texSet - which texture matrix to use
  464.  * In/Out:  t - array [n][4] of texture coordinates to transform
  465.  */
  466. static void transform_texcoords( GLcontext *ctx, GLuint n, GLfloat t[][4],
  467.                  GLuint texSet )
  468. {
  469. #ifndef USE_X86_ASM
  470.    START_FAST_MATH;
  471.    switch (ctx->TextureMatrixType[texSet]) {
  472.       case MATRIX_GENERAL:
  473.      {
  474.         const GLfloat *m = ctx->TextureMatrix[texSet];
  475.         GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  476.         GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  477.         GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  478.         GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  479.         GLuint i;
  480.         for (i=0;i<n;i++) {
  481.            GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3];
  482.            t[i][0] = m0 * t0 + m4 * t1 + m8  * t2 + m12 * t3;
  483.            t[i][1] = m1 * t0 + m5 * t1 + m9  * t2 + m13 * t3;
  484.            t[i][2] = m2 * t0 + m6 * t1 + m10 * t2 + m14 * t3;
  485.            t[i][3] = m3 * t0 + m7 * t1 + m11 * t2 + m15 * t3;
  486.         }
  487.      }
  488.      break;
  489.       case MATRIX_IDENTITY:
  490.      /* Do nothing */
  491.      break;
  492.       case MATRIX_2D:
  493.      {
  494.         const GLfloat *m = ctx->TextureMatrix[texSet];
  495.         GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  496.         GLfloat m12 = m[12], m13 = m[13];
  497.         GLuint i;
  498.         for (i=0;i<n;i++) {
  499.            GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3];
  500.            t[i][0] = m0 * t0 + m4 * t1            + m12 * t3;
  501.            t[i][1] = m1 * t0 + m5 * t1            + m13 * t3;
  502.            t[i][2] =                   +       t2           ;
  503.            /*t[i][3] unchanged*/
  504.         }
  505.      }
  506.      break;
  507.       case MATRIX_3D:
  508.      {
  509.         const GLfloat *m = ctx->TextureMatrix[texSet];
  510.         GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
  511.         GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
  512.         GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
  513.         GLuint i;
  514.         for (i=0;i<n;i++) {
  515.            GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3];
  516.            t[i][0] = m0 * t0 + m4 * t1 +  m8 * t2 + m12 * t3;
  517.            t[i][1] = m1 * t0 + m5 * t1 +  m9 * t2 + m13 * t3;
  518.            t[i][2] = m2 * t0 + m6 * t1 + m10 * t2 + m14 * t3;
  519.            /*t[i][3] unchanged*/
  520.         }
  521.      }
  522.      break;
  523.       default:
  524.      /* should never get here */
  525.      gl_problem( NULL, "invalid matrix type in transform_texcoords()" );
  526.    }
  527.    END_FAST_MATH;
  528. #else
  529.    switch (ctx->TextureMatrixType[texSet]) {
  530. #ifndef __STORM__
  531.       case MATRIX_GENERAL:
  532.      asm_transform_points4_general( n, t, ctx->TextureMatrix[texSet], t );
  533.      break;
  534.       case MATRIX_IDENTITY:
  535.      /* Do nothing */
  536.      break;
  537.       case MATRIX_2D:
  538.      asm_transform_points4_2d( n, t, ctx->TextureMatrix[texSet], t );
  539.      break;
  540.       case MATRIX_3D:
  541.      asm_transform_points4_3d( n, t, ctx->TextureMatrix[texSet], t );
  542.      break;
  543. #else
  544.       case MATRIX_GENERAL:
  545.      asm_transform_points4_general( n, t, ctx->TextureMatrix[texSet], (CONST GLfloat(*)[4])t );
  546.      break;
  547.       case MATRIX_IDENTITY:
  548.      /* Do nothing */
  549.      break;
  550.       case MATRIX_2D:
  551.      asm_transform_points4_2d( n, t, ctx->TextureMatrix[texSet], (CONST GLfloat(*)[4])t );
  552.      break;
  553.       case MATRIX_3D:
  554.      asm_transform_points4_3d( n, t, ctx->TextureMatrix[texSet], (CONST GLfloat(*)[4])t );
  555.      break;
  556. #endif
  557.       default:
  558.      /* should never get here */
  559.      gl_problem( NULL, "invalid matrix type in transform_texcoords()" );
  560.      return;
  561.    }
  562. #endif
  563. }
  564.  
  565.  
  566.  
  567. /*
  568.  * Apply the projection matrix to an array of vertices in Eye coordinates
  569.  * resulting in Clip coordinates.  Also, compute the ClipMask bitfield for
  570.  * each vertex.
  571.  *
  572.  * NOTE: the volatile keyword is used in this function to ensure that the
  573.  * FP computations are computed to low-precision.  If high precision is
  574.  * used (ala 80-bit X86 arithmetic) then the clipMask results may be
  575.  * inconsistant with the computations in clip.c.  Later, clipped polygons
  576.  * may be rendered incorrectly.
  577.  *
  578.  * Input:  ctx - the context
  579.  *         n - number of vertices
  580.  *         vEye - array [n][4] of Eye coordinates
  581.  * Output:  vClip - array [n][4] of Clip coordinates
  582.  *          clipMask - array [n] of clip masks
  583.  */
  584. static void project_and_cliptest( GLcontext *ctx,
  585.                   GLuint n, CONST GLfloat vEye[][4],
  586.                   GLfloat vClip[][4], GLubyte clipMask[],
  587.                   GLubyte *orMask, GLubyte *andMask )
  588.  
  589. {
  590. #ifndef USE_X86_ASM
  591.    GLubyte tmpOrMask = *orMask;
  592.    GLubyte tmpAndMask = *andMask;
  593.  
  594.    START_FAST_MATH;
  595.  
  596.    switch (ctx->ProjectionMatrixType) {
  597.       case MATRIX_GENERAL:
  598.      {
  599.         const GLfloat *m = ctx->ProjectionMatrix;
  600.         GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  601.         GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  602.         GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  603.         GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  604.         GLuint i;
  605.         for (i=0;i<n;i++) {
  606.            GLfloat ex = vEye[i][0], ey = vEye[i][1];
  607.            GLfloat ez = vEye[i][2], ew = vEye[i][3];
  608.            GLfloat cx = m0 * ex + m4 * ey + m8  * ez + m12 * ew;
  609.            GLfloat cy = m1 * ex + m5 * ey + m9  * ez + m13 * ew;
  610.            GLfloat cz = m2 * ex + m6 * ey + m10 * ez + m14 * ew;
  611.            GLfloat cw = m3 * ex + m7 * ey + m11 * ez + m15 * ew;
  612.            GLubyte mask = 0;
  613.            vClip[i][0] = cx;
  614.            vClip[i][1] = cy;
  615.            vClip[i][2] = cz;
  616.            vClip[i][3] = cw;
  617.            if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
  618.            else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
  619.            if (cy >  cw)       mask |= CLIP_TOP_BIT;
  620.            else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
  621.            if (cz >  cw)       mask |= CLIP_FAR_BIT;
  622.            else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
  623.            if (mask) {
  624.           clipMask[i] |= mask;
  625.           tmpOrMask |= mask;
  626.            }
  627.            tmpAndMask &= mask;
  628.         }
  629.      }
  630.      break;
  631.       case MATRIX_IDENTITY:
  632.      {
  633.         GLuint i;
  634.         for (i=0;i<n;i++) {
  635.            GLfloat cx = vClip[i][0] = vEye[i][0];
  636.            GLfloat cy = vClip[i][1] = vEye[i][1];
  637.            GLfloat cz = vClip[i][2] = vEye[i][2];
  638.            GLfloat cw = vClip[i][3] = vEye[i][3];
  639.            GLubyte mask = 0;
  640.            if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
  641.            else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
  642.            if (cy >  cw)       mask |= CLIP_TOP_BIT;
  643.            else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
  644.            if (cz >  cw)       mask |= CLIP_FAR_BIT;
  645.            else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
  646.            if (mask) {
  647.           clipMask[i] |= mask;
  648.           tmpOrMask |= mask;
  649.            }
  650.            tmpAndMask &= mask;
  651.         }
  652.      }
  653.      break;
  654.       case MATRIX_ORTHO:
  655.      {
  656.         const GLfloat *m = ctx->ProjectionMatrix;
  657.         GLfloat m0 = m[0], m5 = m[5], m10 = m[10], m12 = m[12];
  658.         GLfloat m13 = m[13], m14 = m[14];
  659.         GLuint i;
  660.         for (i=0;i<n;i++) {
  661.            GLfloat ex = vEye[i][0], ey = vEye[i][1];
  662.            GLfloat ez = vEye[i][2], ew = vEye[i][3];
  663.            volatile GLfloat cx = m0 * ex                      + m12 * ew;
  664.            volatile GLfloat cy =           m5 * ey            + m13 * ew;
  665.            volatile GLfloat cz =                     m10 * ez + m14 * ew;
  666.            volatile GLfloat cw =                                      ew;
  667.            GLubyte mask = 0;
  668.            vClip[i][0] = cx;
  669.            vClip[i][1] = cy;
  670.            vClip[i][2] = cz;
  671.            vClip[i][3] = cw;
  672.            if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
  673.            else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
  674.            if (cy >  cw)       mask |= CLIP_TOP_BIT;
  675.            else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
  676.            if (cz >  cw)       mask |= CLIP_FAR_BIT;
  677.            else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
  678.            if (mask) {
  679.           clipMask[i] |= mask;
  680.           tmpOrMask |= mask;
  681.            }
  682.            tmpAndMask &= mask;
  683.         }
  684.      }
  685.      break;
  686.       case MATRIX_PERSPECTIVE:
  687.      {
  688.         const GLfloat *m = ctx->ProjectionMatrix;
  689.         GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
  690.         GLfloat m10 = m[10], m14 = m[14];
  691.         GLuint i;
  692.         for (i=0;i<n;i++) {
  693.            GLfloat ex = vEye[i][0], ey = vEye[i][1];
  694.            GLfloat ez = vEye[i][2], ew = vEye[i][3];
  695.            volatile GLfloat cx = m0 * ex           + m8  * ez           ;
  696.            volatile GLfloat cy =           m5 * ey + m9  * ez           ;
  697.            volatile GLfloat cz =                     m10 * ez + m14 * ew;
  698.            volatile GLfloat cw =                          -ez           ;
  699.            GLubyte mask = 0;
  700.            vClip[i][0] = cx;
  701.            vClip[i][1] = cy;
  702.            vClip[i][2] = cz;
  703.            vClip[i][3] = cw;
  704.            if (cx >  cw)       mask |= CLIP_RIGHT_BIT;
  705.            else if (cx < -cw)  mask |= CLIP_LEFT_BIT;
  706.            if (cy >  cw)       mask |= CLIP_TOP_BIT;
  707.            else if (cy < -cw)  mask |= CLIP_BOTTOM_BIT;
  708.            if (cz >  cw)       mask |= CLIP_FAR_BIT;
  709.            else if (cz < -cw)  mask |= CLIP_NEAR_BIT;
  710.            if (mask) {
  711.           clipMask[i] |= mask;
  712.           tmpOrMask |= mask;
  713.            }
  714.            tmpAndMask &= mask;
  715.         }
  716.      }
  717.      break;
  718.       default:
  719.      /* should never get here */
  720.      gl_problem( NULL, "invalid matrix type in project_and_cliptest()" );
  721.    }
  722.  
  723.    *orMask = tmpOrMask;
  724.    *andMask = tmpAndMask;
  725.    END_FAST_MATH;
  726. #else
  727.    switch (ctx->ProjectionMatrixType) {
  728.       case MATRIX_GENERAL:
  729.      asm_project_and_cliptest_general( n, vClip, ctx->ProjectionMatrix, vEye, 
  730.                        clipMask, orMask, andMask );
  731.      break;
  732.       case MATRIX_IDENTITY:
  733.      asm_project_and_cliptest_identity( n, vClip, vEye, clipMask, orMask, andMask );
  734.      break;
  735.       case MATRIX_ORTHO:
  736.      asm_project_and_cliptest_ortho( n, vClip, ctx->ProjectionMatrix, vEye, 
  737.                      clipMask, orMask, andMask );
  738.      break;
  739.       case MATRIX_PERSPECTIVE:
  740.      asm_project_and_cliptest_perspective( n, vClip, ctx->ProjectionMatrix,
  741.                            vEye, clipMask, orMask, andMask );
  742.      break;
  743.       default:
  744.      /* should never get here */
  745.      gl_problem( NULL, "invalid matrix type in project_and_cliptest()" );
  746.      return;
  747.    }
  748. #endif
  749. }
  750.  
  751.  
  752. /* This value matches the one in clip.c, used to cope with numeric error. */
  753. #define MAGIC_NUMBER -0.8e-03F
  754.  
  755. /*
  756.  * Test an array of vertices against the user-defined clipping planes.
  757.  * Input:  ctx - the context
  758.  *         n - number of vertices
  759.  *         vEye - array [n] of vertices, in eye coordinate system
  760.  * Output:  clipMask - array [n] of clip values: 0=not clipped, !0=clipped
  761.  * Return:  CLIP_ALL - if all vertices are clipped by one of the planes
  762.  *          CLIP_NONE - if no vertices were clipped
  763.  *          CLIP_SOME - if some vertices were clipped
  764.  */
  765. static GLuint userclip_vertices( GLcontext *ctx, GLuint n,
  766.                  CONST GLfloat vEye[][4],
  767.                  GLubyte clipMask[] )
  768. {
  769.    GLboolean anyClipped = GL_FALSE;
  770.    GLuint p;
  771.  
  772.    ASSERT(ctx->Transform.AnyClip);
  773.  
  774.    START_FAST_MATH;
  775.  
  776.    for (p=0;p<MAX_CLIP_PLANES;p++) {
  777.       if (ctx->Transform.ClipEnabled[p]) {
  778.      GLfloat a = ctx->Transform.ClipEquation[p][0];
  779.      GLfloat b = ctx->Transform.ClipEquation[p][1];
  780.      GLfloat c = ctx->Transform.ClipEquation[p][2];
  781.      GLfloat d = ctx->Transform.ClipEquation[p][3];
  782.      GLboolean allClipped = GL_TRUE;
  783.      GLuint i;
  784.      for (i=0;i<n;i++) {
  785.         GLfloat dot = vEye[i][0] * a + vEye[i][1] * b
  786.             + vEye[i][2] * c + vEye[i][3] * d;
  787.         if (dot < MAGIC_NUMBER) {
  788.            /* this vertex is clipped */
  789.            clipMask[i] = CLIP_USER_BIT;
  790.            anyClipped = GL_TRUE;
  791.         }
  792.         else {
  793.            /* vertex not clipped */
  794.            allClipped = GL_FALSE;
  795.         }
  796.      }
  797.      if (allClipped) {
  798.         return CLIP_ALL;
  799.      }
  800.       }
  801.    }
  802.  
  803.    END_FAST_MATH;
  804.  
  805.    return anyClipped ? CLIP_SOME : CLIP_NONE;
  806. }
  807.  
  808.  
  809. /*
  810.  * Transform an array of vertices from clip coordinate space to window
  811.  * coordinates.
  812.  * Input:  ctx - the context
  813.  *         n - number of vertices to transform
  814.  *         vClip - array [n] of input vertices
  815.  *         clipMask - array [n] of vertex clip masks.  NULL = no clipped verts
  816.  * Output:  vWin - array [n] of vertices in window coordinate system
  817.  */
  818. static void viewport_map_vertices( GLcontext *ctx,
  819.                    GLuint n, CONST GLfloat vClip[][4],
  820.                    const GLubyte clipMask[], GLfloat vWin[][3])
  821. {
  822.  
  823.    GLfloat sx = ctx->Viewport.Sx;
  824.    GLfloat tx = ctx->Viewport.Tx;
  825.    GLfloat sy = ctx->Viewport.Sy;
  826.    GLfloat ty = ctx->Viewport.Ty;
  827.    GLfloat sz = ctx->Viewport.Sz;
  828.    GLfloat tz = ctx->Viewport.Tz;
  829.  
  830.  
  831.    START_FAST_MATH;
  832.  
  833.    if ((ctx->ProjectionMatrixType==MATRIX_ORTHO || 
  834.     ctx->ProjectionMatrixType==MATRIX_IDENTITY)
  835.        && ctx->ModelViewMatrixType!=MATRIX_GENERAL
  836.        && (ctx->VB->VertexSizeMask & VERTEX4_BIT)==0) {
  837.       /* don't need to divide by W */
  838. #if !defined(AMIGA) || !defined(__PPC__)
  839.       if (clipMask) {
  840.      /* one or more vertices are clipped */
  841.      GLuint i;
  842.      for (i=0;i<n;i++) {
  843.         if (clipMask[i]==0) {
  844.            vWin[i][0] = vClip[i][0] * sx + tx;
  845.            vWin[i][1] = vClip[i][1] * sy + ty;
  846.            vWin[i][2] = vClip[i][2] * sz + tz;
  847.         }
  848.      }
  849.       }
  850.       else {
  851.      /* no vertices are clipped */
  852.      GLuint i;
  853.      for (i=0;i<n;i++) {
  854.         vWin[i][0] = vClip[i][0] * sx + tx;
  855.         vWin[i][1] = vClip[i][1] * sy + ty;
  856.         vWin[i][2] = vClip[i][2] * sz + tz;
  857.      }
  858.       }
  859. #else
  860.       asm_vp_map_vertices_now(clipMask,n,vWin,vClip,sx,sy,sz,tx,ty,tz);
  861. #endif
  862.    }
  863.    else {
  864. #if !defined(AMIGA) || !defined(__PPC__)
  865.       /* need to divide by W */
  866.       if (clipMask) {
  867.      /* one or more vertices are clipped */
  868.      GLuint i;
  869.      for (i=0;i<n;i++) {
  870.         if (clipMask[i] == 0) {
  871.            if (vClip[i][3] != 0.0F) {
  872.           GLfloat wInv = 1.0F / vClip[i][3];
  873.           vWin[i][0] = vClip[i][0] * wInv * sx + tx;
  874.           vWin[i][1] = vClip[i][1] * wInv * sy + ty;
  875.           vWin[i][2] = vClip[i][2] * wInv * sz + tz;
  876.            }
  877.            else {
  878.           /* Div by zero!  Can't set window coords to infinity, so...*/
  879.           vWin[i][0] = 0.0F;
  880.           vWin[i][1] = 0.0F;
  881.           vWin[i][2] = 0.0F;
  882.            }
  883.         }
  884.      }
  885.       }
  886.       else {
  887.      /* no vertices are clipped */
  888.      GLuint i;
  889.      for (i=0;i<n;i++) {
  890.         if (vClip[i][3] != 0.0F) {
  891.            GLfloat wInv = 1.0F / vClip[i][3];
  892.            vWin[i][0] = vClip[i][0] * wInv * sx + tx;
  893.            vWin[i][1] = vClip[i][1] * wInv * sy + ty;
  894.            vWin[i][2] = vClip[i][2] * wInv * sz + tz;
  895.         }
  896.         else {
  897.            /* Divide by zero!  Can't set window coords to infinity, so...*/
  898.            vWin[i][0] = 0.0F;
  899.            vWin[i][1] = 0.0F;
  900.            vWin[i][2] = 0.0F;
  901.         }
  902.      }
  903.       }
  904. #else
  905.       asm_vp_map_vertices(clipMask,n,vWin,vClip,sx,sy,sz,tx,ty,tz);
  906. #endif
  907.    }
  908.  
  909.    END_FAST_MATH;
  910. }
  911.  
  912.  
  913.  
  914. /*
  915.  * Check if the global material has to be updated with info that was
  916.  * associated with a vertex via glMaterial.
  917.  * This function is used when any material values get changed between
  918.  * glBegin/glEnd either by calling glMaterial() or by calling glColor()
  919.  * when GL_COLOR_MATERIAL is enabled.
  920.  */
  921. static void update_material( GLcontext *ctx, GLuint i )
  922. {
  923.    struct vertex_buffer *VB = ctx->VB;
  924.  
  925.    if (VB->MaterialMask[i]) {
  926.       if (VB->MaterialMask[i] & FRONT_AMBIENT_BIT) {
  927.      COPY_4V( ctx->Light.Material[0].Ambient, VB->Material[i][0].Ambient );
  928.       }
  929.       if (VB->MaterialMask[i] & BACK_AMBIENT_BIT) {
  930.      COPY_4V( ctx->Light.Material[1].Ambient, VB->Material[i][1].Ambient );
  931.       }
  932.       if (VB->MaterialMask[i] & FRONT_DIFFUSE_BIT) {
  933.      COPY_4V( ctx->Light.Material[0].Diffuse, VB->Material[i][0].Diffuse );
  934.       }
  935.       if (VB->MaterialMask[i] & BACK_DIFFUSE_BIT) {
  936.      COPY_4V( ctx->Light.Material[1].Diffuse, VB->Material[i][1].Diffuse );
  937.       }
  938.       if (VB->MaterialMask[i] & FRONT_SPECULAR_BIT) {
  939.      COPY_4V( ctx->Light.Material[0].Specular, VB->Material[i][0].Specular );
  940.       }
  941.       if (VB->MaterialMask[i] & BACK_SPECULAR_BIT) {
  942.      COPY_4V( ctx->Light.Material[1].Specular, VB->Material[i][1].Specular );
  943.       }
  944.       if (VB->MaterialMask[i] & FRONT_EMISSION_BIT) {
  945.      COPY_4V( ctx->Light.Material[0].Emission, VB->Material[i][0].Emission );
  946.       }
  947.       if (VB->MaterialMask[i] & BACK_EMISSION_BIT) {
  948.      COPY_4V( ctx->Light.Material[1].Emission, VB->Material[i][1].Emission );
  949.       }
  950.       if (VB->MaterialMask[i] & FRONT_SHININESS_BIT) {
  951.      ctx->Light.Material[0].Shininess = VB->Material[i][0].Shininess;
  952.      gl_compute_material_shine_table( &ctx->Light.Material[0] );
  953.       }
  954.       if (VB->MaterialMask[i] & BACK_SHININESS_BIT) {
  955.      ctx->Light.Material[1].Shininess = VB->Material[i][1].Shininess;
  956.      gl_compute_material_shine_table( &ctx->Light.Material[1] );
  957.       }
  958.       if (VB->MaterialMask[i] & FRONT_INDEXES_BIT) {
  959.      ctx->Light.Material[0].AmbientIndex = VB->Material[i][0].AmbientIndex;
  960.      ctx->Light.Material[0].DiffuseIndex = VB->Material[i][0].DiffuseIndex;
  961.      ctx->Light.Material[0].SpecularIndex = VB->Material[i][0].SpecularIndex;
  962.       }
  963.       if (VB->MaterialMask[i] & BACK_INDEXES_BIT) {
  964.      ctx->Light.Material[1].AmbientIndex = VB->Material[i][1].AmbientIndex;
  965.      ctx->Light.Material[1].DiffuseIndex = VB->Material[i][1].DiffuseIndex;
  966.      ctx->Light.Material[1].SpecularIndex = VB->Material[i][1].SpecularIndex;
  967.       }
  968.       VB->MaterialMask[i] = 0;  /* reset now */
  969.    }
  970. }
  971.  
  972.  
  973. /*
  974.  * Compute the shading (lighting) for the vertices in the vertex buffer.
  975.  */
  976. static void shade_vertices( GLcontext *ctx, GLuint vbStart, GLuint vbCount )
  977. {
  978.    struct vertex_buffer *VB = ctx->VB;
  979.  
  980.    if (ctx->Visual->RGBAflag && ctx->Texture.Enabled
  981.        && ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) {
  982.       /* Separate specular color */
  983.       if (!VB->MonoMaterial) {
  984.      /* Material may change with each vertex */
  985.      GLuint i;
  986.      for (i=vbStart; i<vbCount; i++) {
  987.         update_material( ctx, i );
  988.         gl_shade_rgba_spec( ctx, 0, 1, &VB->Eye[i],
  989.                 &VB->Normal[i], &VB->Fcolor[i], &VB->Fspec[i]);
  990.         if (ctx->Light.Model.TwoSide) {
  991.            gl_shade_rgba_spec( ctx, 1, 1, &VB->Eye[i],
  992.                  &VB->Normal[i], &VB->Bcolor[i], &VB->Bspec[i]);
  993.         }
  994.      }
  995.      /* Need this in case a glColor/glMaterial is called after the
  996.       * last vertex between glBegin/glEnd.
  997.       */
  998.      update_material( ctx, vbCount );
  999.       }
  1000.       else {
  1001.      /* call slower, full-featured shader */
  1002.      gl_shade_rgba_spec( ctx, 0,
  1003.                  vbCount - vbStart,
  1004.                  VB->Eye + vbStart,
  1005.                  VB->Normal + vbStart,
  1006.                  VB->Fcolor + vbStart,
  1007.                  VB->Fspec + vbStart );
  1008.      if (ctx->Light.Model.TwoSide) {
  1009.         gl_shade_rgba_spec( ctx, 1,
  1010.                 vbCount - vbStart,
  1011.                 VB->Eye + vbStart,
  1012.                 VB->Normal + vbStart,
  1013.                 VB->Bcolor + vbStart,
  1014.                 VB->Bspec + vbStart );
  1015.      }
  1016.       }
  1017.    }
  1018.    else if (ctx->Visual->RGBAflag) {
  1019.       if (!VB->MonoMaterial) {
  1020.      /* Material may change with each vertex */
  1021.      GLuint i;
  1022.      for (i=vbStart; i<vbCount; i++) {
  1023.         update_material( ctx, i );
  1024.         gl_shade_rgba( ctx, 0, 1, &VB->Eye[i],
  1025.                &VB->Normal[i], &VB->Fcolor[i]);
  1026.         if (ctx->Light.Model.TwoSide) {
  1027.            gl_shade_rgba( ctx, 1, 1, &VB->Eye[i],
  1028.                   &VB->Normal[i], &VB->Bcolor[i]);
  1029.         }
  1030.      }
  1031.      /* Need this in case a glColor/glMaterial is called after the
  1032.       * last vertex between glBegin/glEnd.
  1033.       */
  1034.      update_material( ctx, vbCount );
  1035.       }
  1036.       else {
  1037.      if (ctx->Light.Fast) {
  1038.         if (VB->MonoNormal) {
  1039.            /* call optimized shader */
  1040.            GLubyte color[1][4];
  1041.            GLuint i;
  1042.            gl_shade_rgba_fast( ctx, 0,  /* front side */
  1043.                    1, VB->Normal + vbStart, color );
  1044.            for (i=vbStart; i<vbCount; i++) {
  1045.           COPY_4V( VB->Fcolor[i], color[0] );
  1046.            }
  1047.            if (ctx->Light.Model.TwoSide) {
  1048.           gl_shade_rgba_fast( ctx, 1,  /* back side */
  1049.                       1, VB->Normal + vbStart, color );
  1050.           for (i=vbStart; i<vbCount; i++) {
  1051.              COPY_4V( VB->Bcolor[i], color[0] );
  1052.           }
  1053.            }
  1054.  
  1055.         }
  1056.         else {
  1057.            /* call optimized shader */
  1058.            gl_shade_rgba_fast( ctx, 0,  /* front side */
  1059.                    vbCount - vbStart,
  1060.                    VB->Normal + vbStart,
  1061.                    VB->Fcolor + vbStart );
  1062.            if (ctx->Light.Model.TwoSide) {
  1063.           gl_shade_rgba_fast( ctx, 1,  /* back side */
  1064.                       vbCount - vbStart,
  1065.                       VB->Normal + vbStart,
  1066.                       VB->Bcolor + vbStart );
  1067.            }
  1068.         }
  1069.      }
  1070.      else {
  1071.         /* call slower, full-featured shader */
  1072.         gl_shade_rgba( ctx, 0,
  1073.                vbCount - vbStart,
  1074.                VB->Eye + vbStart,
  1075.                VB->Normal + vbStart,
  1076.                VB->Fcolor + vbStart );
  1077.         if (ctx->Light.Model.TwoSide) {
  1078.            gl_shade_rgba( ctx, 1,
  1079.                   vbCount - vbStart,
  1080.                   VB->Eye + vbStart,
  1081.                   VB->Normal + vbStart,
  1082.                   VB->Bcolor + vbStart );
  1083.         }
  1084.      }
  1085.       }
  1086.    }
  1087.    else {
  1088.       /* Color index mode */
  1089.       if (!VB->MonoMaterial) {
  1090.      /* Material may change with each vertex */
  1091.      GLuint i;
  1092.      /* NOTE the <= here.  This is needed in case glColor/glMaterial
  1093.       * is called after the last glVertex inside a glBegin/glEnd pair.
  1094.       */
  1095.      for (i=vbStart; i<vbCount; i++) {
  1096.         update_material( ctx, i );
  1097.         gl_shade_ci( ctx, 0, 1, &VB->Eye[i],
  1098.              &VB->Normal[i], &VB->Findex[i] );
  1099.         if (ctx->Light.Model.TwoSide) {
  1100.            gl_shade_ci( ctx, 1, 1, &VB->Eye[i],
  1101.                 &VB->Normal[i], &VB->Bindex[i] );
  1102.         }
  1103.      }
  1104.      /* Need this in case a glColor/glMaterial is called after the
  1105.       * last vertex between glBegin/glEnd.
  1106.       */
  1107.      update_material( ctx, vbCount );
  1108.       }
  1109.       else {
  1110.      gl_shade_ci( ctx, 0,
  1111.               vbCount - vbStart,
  1112.               VB->Eye + vbStart,
  1113.               VB->Normal + vbStart,
  1114.               VB->Findex + vbStart );
  1115.      if (ctx->Light.Model.TwoSide) {
  1116.         gl_shade_ci( ctx, 1,
  1117.              vbCount - vbStart,
  1118.              VB->Eye + vbStart,
  1119.              VB->Normal + vbStart,
  1120.              VB->Bindex + vbStart );
  1121.      }
  1122.       }
  1123.    }
  1124. }
  1125.  
  1126.  
  1127.  
  1128. /*
  1129.  * Compute fog for the vertices in the vertex buffer.
  1130.  */
  1131. static void fog_vertices( GLcontext *ctx, GLuint vbStart, GLuint vbCount )
  1132. {
  1133.    struct vertex_buffer *VB = ctx->VB;
  1134.  
  1135.    if (ctx->Visual->RGBAflag) {
  1136.       /* Fog RGB colors */
  1137.       gl_fog_rgba_vertices( ctx, vbCount - vbStart,
  1138.                 VB->Eye + vbStart,
  1139.                 VB->Fcolor + vbStart );
  1140.       if (ctx->LightTwoSide) {
  1141.      gl_fog_rgba_vertices( ctx, vbCount - vbStart,
  1142.                    VB->Eye + vbStart,
  1143.                    VB->Bcolor + vbStart );
  1144.       }
  1145.    }
  1146.    else {
  1147.       /* Fog color indexes */
  1148.       gl_fog_ci_vertices( ctx, vbCount - vbStart,
  1149.               VB->Eye + vbStart,
  1150.               VB->Findex + vbStart );
  1151.       if (ctx->LightTwoSide) {
  1152.      gl_fog_ci_vertices( ctx, vbCount - vbStart,
  1153.                  VB->Eye + vbStart,
  1154.                  VB->Bindex + vbStart );
  1155.       }
  1156.    }
  1157. }
  1158.  
  1159.  
  1160. /*
  1161.  * Transform vertices, compute lighting, clipflags,
  1162.  * fog, texture coords, etc.
  1163.  *
  1164.  * Return the clipOrMask and clipAndMask values for the given VB range
  1165.  */
  1166. static void gl_transform_vb_range( GLcontext *ctx, GLuint vbStart, GLuint vbCount,
  1167.                    GLubyte *clipOrMask, GLubyte *clipAndMask,
  1168.                    GLboolean firstPartToDo)
  1169. {
  1170.   struct vertex_buffer *VB = ctx->VB;
  1171.  
  1172.     START_PROFILE3
  1173.   if (firstPartToDo) {
  1174.     /* Apply the modelview matrix to transform vertexes from Object
  1175.      * to Eye coords.
  1176.      */
  1177.     if (VB->VertexSizeMask==VERTEX4_BIT) {
  1178. #ifndef __STORM__
  1179.       transform_points4( ctx, vbCount - vbStart,
  1180.              VB->Obj + vbStart, VB->Eye + vbStart );
  1181. #else
  1182.       transform_points4( ctx, vbCount - vbStart,
  1183.              (CONST GLfloat(*)[4])(VB->Obj + vbStart), VB->Eye + vbStart );
  1184. #endif
  1185.     }
  1186.     else {
  1187. #ifndef __STORM__
  1188.       transform_points3( ctx, vbCount - vbStart,
  1189.              VB->Obj + vbStart, VB->Eye + vbStart );
  1190. #else
  1191.       transform_points3( ctx, vbCount - vbStart,
  1192.              (CONST GLfloat(*)[4])(VB->Obj + vbStart), VB->Eye + vbStart );
  1193. #endif
  1194.     }
  1195.  
  1196.     /* Now transform the normal vectors */
  1197.     if (ctx->NeedNormals) {
  1198.       gl_xform_normals_3fv( vbCount - vbStart,
  1199.                 VB->Normal + vbStart, ctx->ModelViewInv,
  1200.                 VB->Normal + vbStart, ctx->Transform.Normalize,
  1201.                 ctx->Transform.RescaleNormals );
  1202.     }
  1203.   }
  1204.     END_PROFILE3(prof1_time)
  1205.     START_PROFILE3
  1206.  
  1207.   /* Test vertices in eye coordinate space against user clipping planes */
  1208.   if (ctx->Transform.AnyClip) {
  1209. #ifndef __STORM__
  1210.     GLuint result = userclip_vertices( ctx, vbCount - vbStart,
  1211.                        VB->Eye + vbStart,
  1212.                        VB->ClipMask + vbStart );
  1213. #else
  1214.     GLuint result = userclip_vertices( ctx, vbCount - vbStart,
  1215.                        (CONST GLfloat(*)[4])(VB->Eye + vbStart),
  1216.                        VB->ClipMask + vbStart );
  1217. #endif
  1218.     if (result==CLIP_ALL) {
  1219.       /* All vertices were outside one of the clip planes! */
  1220.       *clipOrMask = CLIP_ALL_BITS; /* force reset of clipping flags */
  1221.       *clipAndMask = CLIP_ALL_BITS;
  1222.       return;
  1223.     }
  1224.     else if (result==CLIP_SOME) {
  1225.       *clipOrMask = CLIP_USER_BIT;
  1226.     }
  1227.     else {
  1228.       *clipAndMask = 0;
  1229.     }
  1230.   }
  1231.     END_PROFILE3(prof2_time)
  1232.     START_PROFILE3
  1233.  
  1234.   /* Apply the projection matrix to the Eye coordinates, resulting in
  1235.    * Clip coordinates.  Also, compute the ClipMask for each vertex.
  1236.    */
  1237. #ifndef __STORM__
  1238.   project_and_cliptest( ctx, vbCount - vbStart, VB->Eye + vbStart,
  1239.             VB->Clip + vbStart, VB->ClipMask + vbStart,
  1240.             clipOrMask, clipAndMask );
  1241. #else
  1242.   project_and_cliptest( ctx, vbCount - vbStart, (CONST GLfloat(*)[4])(VB->Eye + vbStart),
  1243.             VB->Clip + vbStart, VB->ClipMask + vbStart,
  1244.             clipOrMask, clipAndMask );
  1245. #endif
  1246.   if (*clipAndMask) {
  1247.     /* All vertices clipped by one plane, all done! */
  1248.     *clipOrMask = CLIP_ALL_BITS; /* force reset of clipping flags */
  1249.     return;
  1250.   }
  1251.     END_PROFILE3(prof3_time)
  1252.     START_PROFILE3
  1253.  
  1254.   /* Lighting */
  1255.   if (ctx->Light.Enabled) {
  1256.     shade_vertices(ctx, vbStart, vbCount);
  1257.   }
  1258.     END_PROFILE3(prof4_time)
  1259.     START_PROFILE3
  1260.  
  1261.   /* Per-vertex fog */
  1262.   if (ctx->Fog.Enabled && ctx->Hint.Fog!=GL_NICEST) {
  1263.     fog_vertices(ctx, vbStart, vbCount);
  1264.   }
  1265.     END_PROFILE3(prof5_time)
  1266.     START_PROFILE3
  1267.  
  1268.   /* Generate/transform texture coords */
  1269.   if (ctx->Texture.Enabled || ctx->RenderMode==GL_FEEDBACK) {
  1270.     GLuint texSet;
  1271.     for (texSet=0; texSet<MAX_TEX_COORD_SETS; texSet++) {
  1272.       if (ctx->Texture.Set[texSet].TexGenEnabled) {
  1273.     gl_texgen( ctx, vbCount - vbStart,
  1274.            VB->Obj + vbStart,
  1275.            VB->Eye + vbStart,
  1276.            VB->Normal + vbStart,
  1277.            VB->MultiTexCoord[texSet] + vbStart,
  1278.            texSet );
  1279.       }
  1280.     }
  1281.     for (texSet=0; texSet<MAX_TEX_COORD_SETS; texSet++) {
  1282.       if (ctx->TextureMatrixType[texSet] != MATRIX_IDENTITY) {
  1283.     transform_texcoords( ctx, vbCount - vbStart,
  1284.                  VB->MultiTexCoord[texSet] + vbStart,
  1285.                  texSet );
  1286.       }
  1287.     }
  1288.   }
  1289.     END_PROFILE3(prof6_time)
  1290.     START_PROFILE3
  1291.   
  1292.   /* Use the viewport parameters to transform vertices from Clip
  1293.    * coordinates to Window coordinates.
  1294.    */
  1295.   if (ctx->DoViewportMapping) {
  1296. #ifndef __STORM__
  1297.      viewport_map_vertices( ctx, vbCount - vbStart, VB->Clip + vbStart,
  1298.              (*clipOrMask) ? VB->ClipMask + vbStart : (GLubyte*) NULL,
  1299.              VB->Win + vbStart );
  1300. #else
  1301.      viewport_map_vertices( ctx, vbCount - vbStart, (CONST GLfloat(*)[4])(VB->Clip + vbStart),
  1302.              (*clipOrMask) ? VB->ClipMask + vbStart : (GLubyte*) NULL,
  1303.              VB->Win + vbStart );
  1304. #endif
  1305.   }
  1306.     END_PROFILE3(prof7_time)
  1307.     START_PROFILE3
  1308.  
  1309.   /* Device driver rasterization setup.  3Dfx driver, for example. */
  1310.   if (ctx->Driver.RasterSetup) {
  1311.     (*ctx->Driver.RasterSetup)( ctx, vbStart, vbCount );
  1312.   }
  1313.     END_PROFILE3(prof8_time)
  1314. }
  1315.  
  1316.  
  1317. #ifdef MITS
  1318.  
  1319. #include <pthread.h>
  1320. #include <semaphore.h>
  1321. #include <sys/time.h>
  1322. #include <sys/resource.h>
  1323. #include <sched.h>
  1324. #include <unistd.h>
  1325.  
  1326.  
  1327. /* Flag to indicate first time through */
  1328. static int firsttime=1;
  1329.  
  1330. /* Semaphores for the vertex buffer processing threads */
  1331. static sem_t tDone1, tDone2;
  1332.  
  1333. pthread_attr_t attr1, attr2;
  1334. pthread_t thread1, thread2;
  1335.  
  1336.  
  1337. typedef struct {
  1338.  
  1339.   GLuint start;
  1340.   GLuint count;
  1341.   GLcontext *ctx;
  1342.   GLboolean firstPartToDo;
  1343.   sem_t *thread_sem;
  1344.   volatile int tsync;
  1345.  
  1346. } GLtsched;
  1347.  
  1348.  
  1349. static  GLtsched set1, set2;
  1350.  
  1351.  
  1352. /* These are the processing threads for the vertex buffer */
  1353. void *gl_transform_vb_range_scheduler(void *s) 
  1354. {
  1355.   struct vertex_buffer *VB;
  1356.   GLtsched *set=(GLtsched *)s;
  1357.  
  1358.   int sval;
  1359.  
  1360.   while(1) {
  1361.  
  1362.     /* Sleep until main thread wakes us up again */
  1363.     sem_wait( set->thread_sem );
  1364.  
  1365.     VB = set->ctx->VB;
  1366.  
  1367.     gl_transform_vb_range( set->ctx, set->start, set->count,
  1368.                &VB->ClipOrMask, &VB->ClipAndMask,
  1369.                set->firstPartToDo );
  1370.     set->tsync = 1;
  1371.  
  1372.   } /* end while */
  1373.  
  1374.   return NULL;
  1375.  
  1376. } /* end gl_transform_vb_range_scheduler */
  1377. #endif
  1378.  
  1379.  
  1380. void gl_transform_vb( GLcontext *ctx, GLboolean firstPartToDo, GLboolean allDone )
  1381. {
  1382.   struct vertex_buffer *VB = ctx->VB;
  1383. #ifdef MITS
  1384.   struct sched_param sparam1, sparam2, mparams;
  1385. #endif
  1386.  
  1387. #ifdef PROFILE
  1388.   GLdouble t0 = gl_time();
  1389. #endif
  1390.  
  1391.   ASSERT( VB->Count>0 );
  1392.  
  1393. #ifdef PROFILE
  1394.   ctx->VertexTime += gl_time() - t0;
  1395.   ctx->VertexCount += VB->Count - VB->Start;
  1396. #endif
  1397.   
  1398.   if ((ctx->Texture.Enabled || ctx->RenderMode==GL_FEEDBACK) &&
  1399.       ctx->NewTextureMatrix)
  1400.     gl_analyze_texture_matrix(ctx);
  1401.  
  1402.   if (ctx->Driver.RasterSetup && VB->Start) {
  1403.       (*ctx->Driver.RasterSetup)( ctx, 0, VB->Start );
  1404.   }
  1405.  
  1406. #ifdef MITS
  1407.  
  1408.   if (VB->Count > 72) {
  1409.  
  1410.     if( firsttime ) {
  1411.  
  1412.       int policy;
  1413.      
  1414.  
  1415.       if( !getuid() ) {
  1416.     policy = SCHED_FIFO;
  1417.       }
  1418.       else {
  1419.     policy = SCHED_OTHER;
  1420.       }
  1421.  
  1422.  
  1423.       mparams.sched_priority = sched_get_priority_max(policy) - 1;
  1424.       sched_setscheduler(0, policy, &mparams);
  1425.  
  1426.       sparam1.sched_priority = sched_get_priority_max(policy);
  1427.       sparam2.sched_priority = sched_get_priority_max(policy);
  1428.  
  1429.  
  1430.       sem_init( &tDone1, 0, 0);
  1431.       sem_init( &tDone2, 0, 0);     
  1432.  
  1433.  
  1434.       /* Set up threads with OTHER policy and maximum priority */
  1435.       pthread_attr_init( &attr1 );
  1436.       pthread_attr_setscope( &attr1, PTHREAD_SCOPE_SYSTEM);
  1437.       pthread_attr_setschedpolicy( &attr1, policy );
  1438.       pthread_attr_setdetachstate( &attr1, PTHREAD_CREATE_DETACHED);
  1439.       pthread_attr_setschedparam( &attr1, &sparam1 );
  1440.  
  1441.       pthread_attr_init( &attr2 );
  1442.       pthread_attr_setscope( &attr2, PTHREAD_SCOPE_SYSTEM);
  1443.       pthread_attr_setschedpolicy( &attr2, policy );
  1444.       pthread_attr_setdetachstate( &attr2, PTHREAD_CREATE_DETACHED);
  1445.       pthread_attr_setschedparam( &attr2, &sparam2 );
  1446.  
  1447.       set1.thread_sem = &tDone1;
  1448.       set2.thread_sem = &tDone2;
  1449.  
  1450.       pthread_create( &thread1, &attr1, gl_transform_vb_range_scheduler, &set1);
  1451.       pthread_create( &thread2, &attr2, gl_transform_vb_range_scheduler, &set2); 
  1452.       firsttime = 0;
  1453.  
  1454.     } /* end if */
  1455.  
  1456.  
  1457.     set1.ctx = ctx;
  1458.     set1.start = VB->Start;
  1459.     set1.count = VB->Start + (VB->Count-VB->Start)/2;
  1460.     set1.firstPartToDo = firstPartToDo;
  1461.  
  1462.  
  1463.     set2.ctx = ctx;
  1464.     set2.start = VB->Start + (VB->Count - VB->Start)/2;
  1465.     set2.count = VB->Count;
  1466.     set2.firstPartToDo = firstPartToDo;
  1467.     
  1468.     set1.tsync = set2.tsync = 0;
  1469.  
  1470.  
  1471.     /* Wake the vertex buffer processing threads */
  1472.     sem_post( &tDone1 );
  1473.     sem_post( &tDone2 );
  1474.     sched_yield();
  1475.  
  1476.  
  1477.     /* Spin until both are done */
  1478.     while( !set1.tsync && !set2.tsync);
  1479.  
  1480.  
  1481.   }
  1482.   else {
  1483.  
  1484.  
  1485.     gl_transform_vb_range( ctx, VB->Start, VB->Count,
  1486.              &VB->ClipOrMask, &VB->ClipAndMask,
  1487.              firstPartToDo );
  1488.  
  1489.   } /* end if */
  1490.  
  1491. #else
  1492.  
  1493.     gl_transform_vb_range( ctx, VB->Start, VB->Count,
  1494.              &VB->ClipOrMask, &VB->ClipAndMask,
  1495.              firstPartToDo );
  1496.  
  1497. #endif
  1498.  
  1499.   if (VB->ClipAndMask) {
  1500.     gl_reset_vb( ctx, allDone );
  1501.     return;
  1502.   }
  1503.  
  1504.  
  1505. #ifdef PROFILE
  1506.   ctx->VertexTime += gl_time() - t0;
  1507.   ctx->VertexCount += VB->Count - VB->Start;
  1508. #endif
  1509.  
  1510.   /*
  1511.    * Now we're ready to rasterize the Vertex Buffer!!!
  1512.    *
  1513.    * If the device driver can't rasterize the vertex buffer then we'll
  1514.    * do it ourselves.
  1515.    */
  1516.   if (!ctx->Driver.RenderVB || !(*ctx->Driver.RenderVB)(ctx,allDone)) {
  1517. #ifdef DRIVEREXT
  1518.     if (ctx->Driver.Lock)
  1519.     (*ctx->Driver.Lock)(ctx);
  1520. #endif
  1521.     START_PROFILE
  1522.     gl_render_vb( ctx, allDone );
  1523.     END_PROFILE(profrender_time)
  1524.  
  1525. #ifdef DRIVEREXT
  1526.     if (ctx->Driver.UnLock)
  1527.     (*ctx->Driver.UnLock)(ctx);
  1528. #endif
  1529.   }
  1530. }
  1531.  
  1532.  
  1533. /*
  1534.  * When the Vertex Buffer is full, this function applies the modelview
  1535.  * matrix to transform vertices and normals from object coordinates to
  1536.  * eye coordinates.  Next, we'll call gl_transform_vb_part2()...
  1537.  * This function might not be called when using vertex arrays.
  1538.  */
  1539. void gl_transform_vb_part1( GLcontext *ctx, GLboolean allDone )
  1540. {
  1541.   gl_transform_vb( ctx, GL_TRUE, allDone );
  1542. }
  1543.  
  1544.  
  1545. /*
  1546.  * Part 2 of Vertex Buffer transformation:  compute lighting, clipflags,
  1547.  * fog, texture coords, etc.
  1548.  * Before this function is called the VB->Eye coordinates must have
  1549.  * already been computed.
  1550.  * Callers:  gl_transform_vb_part1(), glDrawArraysEXT()
  1551.  */
  1552. void gl_transform_vb_part2( GLcontext *ctx, GLboolean allDone )
  1553. {
  1554.   gl_transform_vb( ctx, GL_FALSE, allDone );
  1555. }
  1556.  
  1557.